package gizwits.kit;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;



/**
 * 字节操作
 * @author CHND
 *
 */
public class ByteUtil {
	
	private static Map<Integer,Integer> map;
	
	static{
		map = new HashMap<Integer, Integer>();
		map.put(0, 0x00);
		map.put(1, 0x01);
		map.put(2, 0x03);
		map.put(3, 0x07);
		map.put(4, 0x0f);
		map.put(5, 0x1f);
		map.put(6, 0x3f);
		map.put(7, 0x7f);
		map.put(8, 0xff);
	}
	
	/**
	 * 【整数】转【二进制字符串】
	 */
	public static String toBinaryStr(int source, int len){
		String str = Integer.toBinaryString(source);
		str = zero(str, len, '0');
		return str.substring(str.length()-len);
	}
	
	/**
	 * 【整数】转【十六进制字符串】
	 */
	public static String toHexStr(int source, int len){
		String str = Integer.toHexString(source);
		str = zero(str, len, '0');
		return str.substring(str.length()-len);
	}
	
	/**
	 * 用一串【十六进制字符串】转【字节数组】
	 */
	public static byte[] HexStrToBytes(String str, String split){
		String[] hex = str.split(split);
		byte[] bs = new byte[hex.length];
		int len = 0;
		for(String s : hex){
			bs[len++] = (byte)Integer.parseInt(s,16);
		}
		return bs;
	}
	
	/**
	 * 补零方法
	 */
	private static String zero(String str, int len, char o){
		len = len - str.length();
		StringBuffer buffer = new StringBuffer();
		while(len>0){
			buffer.append(o);
			--len;
		}
		buffer.append(str);
		return buffer.toString();
	}
	
	
	
	/**
	 * 8位【二进制数字符串】转【字节】
	 * @return
	 */
	public static byte toBinary(String byteStr) {
	    int re, len;  
	    if (null == byteStr) {  
	        return 0;  
	    }  
	    len = byteStr.length();  
	    if (0>=len || len>8) {  
	        return 0;  
	    }  
        if (byteStr.charAt(0) == '0') {// 正数  
            re = Integer.parseInt(byteStr, 2);  
        } else {// 负数  
            re = Integer.parseInt(byteStr, 2) - 256;  
        }  
	    return (byte) re;
	}
	
	/**
	 * 【正常模式】【二进制字符串】转【字节数组】
	 */
	public static byte[] toBinarys(String byteStr){
		if((byteStr.length() % 8)!=0)return null;
		int len = byteStr.length()/8;
		byte[] result = new byte[len];
		for(int i=0;i<len;i++){
			result[i] = toBinary(byteStr.substring(i*8,(i*8)+8));
		}
		return result;
	}
	
	/**
	 * 【小端模式】【二进制字符串】转【字节数组】
	 */
	public static byte[] toBinarys2(String byteStr){
		if((byteStr.length() % 8)!=0)return null;
		int len = byteStr.length()/8;
		byte[] result = new byte[len];
		for(int i=0;i<len;i++){
			result[len-1-i] = toBinary(byteStr.substring(i*8,(i*8)+8));
		}
		return result;
	}
	
	/**
	 * 【小端格式】【数字】转【字节数组】
	 */
	public static byte[] toByte(int num,int len){
		byte[] bs = new byte[len];
		for(int i=0;i<len;i++){
			bs[i] = (byte)(0xff & (num >> (i*8)));
		}
		return bs;
	}
	
	/**
	 * 【小端格式的字节数组】转【数字】
	 */
	public static int toInt(byte[] bs,int start,int end){
		int num = 0;
		int len = end - start;
		for(int i=0;i<len;i++){
			num = num | ((bs[i+start] & 0xff) << i * 8);
		}
	    return num;  
	}
	
	/**
	 * 把【一个字节中的几个bit】转【整数】,方向【向右】>
	 */
	@Deprecated
	public static int toIntByRight(byte b, int start, int end) {
		String str = toBinaryStr(b, 8);
		str = str.substring(start,end);
		return toBinary(str);
	}
	
	/**
	 * 把【一个字节中的几个bit】转【整数】,方向【向左】<
	 */
//	@Deprecated
//	public static int toIntByLeft(byte b, int start, int end) {
//		String str = toBinaryStr(b, 8);
//		str = str.substring(8-end,8-start);
//		return toBinary(str);
//	}
	
	
	
	/**
	 * 把【一个字节中的几个bit】转【整数】,方向【向左】<
	 */
	public static int toIntByLeft(byte b, int index, int len) {
		return (b>>index)&map.get(len-index);
	}
	
	/**
	 * 打印【字节数组】
	 */
	public static void printBytes(byte[] array){
		if(array==null){log("字节数组 - 空");return;}
		int id = 1;
		String ten = "";
		String hex = "";
		String two = "";
		for(byte b : array){
			ten += "("+id+++")"+b+" ";
			hex += toHexStr(b, 2)+" ";
			two += toBinaryStr(b, 8)+" ";
		}
		log("十进制:"+ten);
		log("十六进制:"+hex);
		log("二进制:"+two);
		log("字节长度:"+array.length);
	}
	
	/**
	 * 打印【字节数组】,带标题
	 */
	public static void printBytes(String title, byte[] array){
		log("");
		log(title);
		printBytes(array);
		log("");
	}
	
	/**
	 * 把所有【字节数组】合并;【计算【所有字节数组的总长度】并添加到【结果数组的头部】】长度格式【小端格式下的两个字节】
	 * @param os
	 * @return
	 */
	public static byte[] toResult(byte[]... arrays){
		int len = 2;	//len的长度为2
		for(byte[] array : arrays){
			len += array.length;
		}
		byte[] first = toByte(len,2);
		byte[] result = concatAll(first,arrays);
		return result;
	}
	
	/**
	 * 合并【字节数组】【纯合并】
	 * @param first
	 * @param rest
	 * @return
	 */
	public static byte[] concatAll(byte[] first, byte[]... arrays) {
		  int totalLength = first.length;  
		  for (byte[] array : arrays) {  
		    totalLength += array.length;  
		  }  
		  byte[] result = Arrays.copyOf(first, totalLength);
		  int offset = first.length;  
		  for (byte[] array : arrays) {  
		    System.arraycopy(array, 0, result, offset, array.length);  
		    offset += array.length;  
		  }  
		  return result;  
	} 
	
	/**
	 * 输出指针
	 * @param obj
	 */
	private static void log(Object obj){
		System.out.println(obj);
	}
	
	
	/**
	 * 下面是美的专用的
	 */
	
	
	/**
	 * 【判断操作是否成功】检查返回的数组op是否为0,等于0,则用户不存在或者密码错误或者操作失败
	 */
	public static int isWin(byte[] bs){
		return toInt(bs,12,16);
	}
	
	/**
	 * 【判断seqNo是否一致】
	 */
	public static boolean isAlike(byte[] a, byte[] b){
		return toInt(a,16,20)==toInt(b,16,20)?true:false;
	}

	/**
	 * 根据【字节数组前面的【两个字节大小的长度信息】】,截取对应的长度【字节数组】
	 */
	public static byte[] toByte(byte[] bs){
		return Arrays.copyOf(bs, toInt(bs, 0, 2));
	}
	
	public static String printHexString(byte[] message){
		return printHexString("", message);
	}
	
	public static String printHexString(byte b){
		 return Integer.toHexString(b & 0xFF);
	}
	
	public static String printHexString(String msg, byte[] b)
    {    
		StringBuilder sb = new StringBuilder();
        for (int i = 0; i < b.length; i++)    
        {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1)
            {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        } 
        return sb.toString();
    }

	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	/**
	 * Convert char to byte
	 * 
	 * @param c
	 *            char
	 * @return byte
	 */
	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}
}
